#include "DataHandler.h"

static LONG v_cLock = 0;

STDMETHODIMP CClassFactory::QueryInterface( REFIID iid, LPVOID* ppv)
{
	*ppv = NULL;

	if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IClassFactory))
	{
		*ppv = (LPVOID)this;
	}

	if (*ppv != NULL)
	{
		((LPUNKNOWN)*ppv)->AddRef();
		return S_OK;
	}

	return E_NOINTERFACE;
}

STDMETHODIMP_(ULONG) CClassFactory::AddRef()
{
	ULONG urc;

	urc = (ULONG)InterlockedIncrement(&m_cRef);
	return urc;
}

STDMETHODIMP_(ULONG) CClassFactory::Release()
{
	ULONG urc;

	urc = (ULONG)InterlockedDecrement(&m_cRef);
	if (0 == urc)
	{
		delete this;
	}
	return urc;
}

STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN, REFIID, LPVOID*)
{
	return S_OK;
}

STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
{
	if (fLock)
	{
		InterlockedIncrement(&v_cLock);
	}
	else
	{
		InterlockedDecrement(&v_cLock);
	}

	return NO_ERROR;
}

CStore::CStore(LPUNKNOWN pUnknown)
{
	m_cRef = 0;
	m_pUnknown = pUnknown;
	m_pObjHandler = new CDataHandler(this);
}

CStore::~CStore()
{
	delete m_pObjHandler;
}

/* ============ IUnknown part Implementation ====== */
STDMETHODIMP CStore::QueryInterface(REFIID riid, void **ppvObject)
{
	*ppvObject = NULL;

	if (IsEqualIID(riid, IID_IUnknown))
	{
		*ppvObject = (void*)this;
	} else if (IsEqualIID(riid, IID_IReplStore))
	{
		*ppvObject = (IReplStore *)this;
	} else if (IsEqualIID(riid, IID_IReplStore2))
	{
		*ppvObject = (IReplStore2 *)this;
	} else if (m_pUnknown)
	{
		return m_pUnknown->QueryInterface(riid, ppvObject);
	}

	if (*ppvObject)
	{
		((IUnknown *)(*ppvObject))->AddRef();
		return NOERROR;
	}
	return E_NOINTERFACE;
}

STDMETHODIMP_(ULONG) CStore::AddRef()
{
	ULONG urc;

	if (m_pUnknown)
	{
		urc = m_pUnknown->AddRef();
	}
	else
	{
		urc = (ULONG)InterlockedIncrement(&m_cRef);
	}

	return urc;
}

STDMETHODIMP_(ULONG) CStore::Release()
{
	ULONG urc;

	if (m_pUnknown)
	{
		urc = m_pUnknown->Release();
	}
	else
	{
		urc = (ULONG)InterlockedDecrement(&m_cRef);
		if (urc == 0)
		{
			delete this;
		}
	}
	return urc;
}

/* ========= IReplStore methods =============== */

STDMETHODIMP CStore::Initialize(IReplNotify *pNotify, UINT uFlags)
{

	return S_OK;
}

STDMETHODIMP CStore::GetStoreInfo( PSTOREINFO pStoreInfo )
{
	return S_OK;
}

STDMETHODIMP CStore::ReportStatus( HREPLFLD hFolder, HREPLITEM hItem, UINT uStatus, UINT uReserved )
{
	    switch( uStatus )
    {
    case RSC_INTERRUPT:     // client should abort whatever it's doing now
        break;

    case RSC_BEGIN_SYNC:    // ActiveSync service manager is about to start
        break;

    case RSC_END_SYNC:      // ActiveSync service manager is about to end
        break;

    case RSC_BEGIN_CHECK:   // FindFirstItem is about to be called, followed by FindNextItem
        break;

    case RSC_END_CHECK:     // FindItemClose has been called
        break;

    case RSC_DATE_CHANGED:  // System Date has changed
        break;

    case RSC_RELEASE:       // ActiveSync service manager is about to release the service provider
        break;

    case RSC_REMOTE_SYNC:   // Indicates if remote sync is about to start. uParam will TRUE if all sync 
                            // will be remote until this status is reported again with uParam set to FALSE
        break;

    case RSC_BEGIN_SYNC_OBJ:    // ActiveSync service manager is about to start on an object type. uReserved is a pointer to a IEnumReplItem
        break;

    case RSC_END_SYNC_OBJ:      // ActiveSync service manager is about to end on an object type.
        break;

    case RSC_OBJ_TYPE_ENABLED:  // ActiveSync service manager of the given object is enabled, hFolder is indeed a pointer to a string (object type name)
        break;

    case RSC_OBJ_TYPE_DISABLED: // ActiveSync service manager of the given object is disabled, hFolder is indeed a pointer to a string (object type name)
        break;

    case RSC_BEGIN_BATCH_WRITE: // A series of SetPacket will be called on a number of objects, this is the right time for some service providers to start a transaction
        break;

    case RSC_END_BATCH_WRITE:   // above write ends, this is the right time for some service providers to commit the transaction
        break;

    case RSC_CONNECTION_CHG:    // connection status has changed. uParam is TRUE if connection established. FALSE otherwise.
        break;

    case RSC_WRITE_OBJ_FAILED:  // failed writing an object on the device. uParam is the HRESULT code.
        break;

    case RSC_DELETE_OBJ_FAILED: // failed deleting an object on the device. uParam is the HRESULT code.
        break;
    }

    return NOERROR;
}

STDMETHODIMP_(int) CStore::CompareStoreIDs( LPBYTE lpbID1, UINT cbID1, LPBYTE lpbID2, UINT cbID2 )
{
    if ( cbID1 < cbID2 )
        return -1;

    if ( cbID1 > cbID2 )
        return 1;

    return memcmp( lpbID1, lpbID2, cbID1 );
}

// object related routines
STDMETHODIMP_(int) CStore::CompareItem( HREPLITEM hItem1, HREPLITEM hItem2 )
{
	return 1;
}

STDMETHODIMP_(BOOL) CStore::IsItemChanged( HREPLFLD hFolder, HREPLITEM hItem, HREPLITEM hItemComp )
{
	return FALSE;
}
STDMETHODIMP_(BOOL) CStore::IsItemReplicated( HREPLFLD hFolder, HREPLITEM hItem )
{
	return FALSE;
}

STDMETHODIMP_(void) CStore::UpdateItem( HREPLFLD hFolder, HREPLITEM hItemDst, HREPLITEM hItemSrc )
{
}

// folder related routines
STDMETHODIMP CStore::GetFolderInfo( LPCSTR lpszName,  HREPLFLD *phFolder, IUnknown **ppObjHandler )
{
	return NOERROR;
}

STDMETHODIMP CStore::IsFolderChanged( HREPLFLD hFolder, BOOL *pfChanged )
{
	return NOERROR;
}

// enumeration of folder objects
STDMETHODIMP CStore::FindFirstItem( HREPLFLD hFolder,  HREPLITEM *phItem, BOOL *pfExist )
{
	return NOERROR;
}

STDMETHODIMP CStore::FindNextItem( HREPLFLD hFolder,  HREPLITEM *phItem, BOOL *pfExist )
{
	return NOERROR;
}

STDMETHODIMP CStore::FindItemClose( HREPLFLD hFolder )
{
	return NOERROR;
}

// STD management routines
STDMETHODIMP_(UINT) CStore::ObjectToBytes( HREPLOBJ hObject, LPBYTE lpb )
{
}

STDMETHODIMP_(HREPLOBJ) CStore::BytesToObject( LPBYTE lpb, UINT cb )
{
}

STDMETHODIMP_(void) CStore::FreeObject( HREPLOBJ hObject )
{

}

STDMETHODIMP_(BOOL) CStore::CopyObject( HREPLOBJ hObjSrc, HREPLOBJ hObjDst )
{
	return TRUE;
}

STDMETHODIMP CStore::IsValidObject( HREPLFLD hFolder, HREPLITEM hObject, UINT uFlags )
{
}

// UI related routines
STDMETHODIMP CStore::ActivateDialog( UINT uDlg, HWND hwndParent, HREPLFLD hFolder, IEnumReplItem *penum )
{
}

STDMETHODIMP CStore::GetObjTypeUIData( HREPLFLD hFolder, POBJUIDATA pData )
{
}

STDMETHODIMP CStore::GetConflictInfo( PCONFINFO pConfInfo )
{
}

STDMETHODIMP CStore::RemoveDuplicates( LPCSTR, UINT )
{
}